package com.bf.electroplating.util.word;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.*;

/**
 * Word图片提取器
 * 专门用于从Word文档中提取和处理图片
 */
@Slf4j
@Component
public class WordImageExtractor {
    
    /**
     * 从Word文档中提取所有图片并保存到本地
     * @param document Word文档对象
     * @param documentName 文档名称（用于生成文件夹）
     * @return 图片路径映射 Map<图片ID, 本地文件路径>
     */
    public Map<String, String> extractAllImages(XWPFDocument document, String documentName) {
        Map<String, String> imageMap = new HashMap<>();
        
        try {
            // 获取所有图片
            List<XWPFPictureData> allPictures = document.getAllPictures();
            log.info("文档 {} 中找到 {} 张图片", documentName, allPictures.size());
            
            // 创建文档专用目录
            String baseDir = "uploads/word_images/" + 
                java.time.LocalDate.now().toString().replace("-", "/") + "/" +
                sanitizeFileName(documentName) + "/";
            File dir = new File(baseDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 保存每张图片
            for (int i = 0; i < allPictures.size(); i++) {
                XWPFPictureData picture = allPictures.get(i);
                String pictureId = "picture_" + i; // 使用索引作为ID
                String originalFileName = picture.getFileName();
                
                // 生成新的文件名
                String newFileName = generateImageFileName(originalFileName, i);
                String filePath = baseDir + newFileName;
                
                // 保存图片
                if (saveImageToFile(picture, filePath)) {
                    imageMap.put(pictureId, filePath);
                    log.info("保存图片: {} -> {}", originalFileName, filePath);
                }
            }
            
        } catch (Exception e) {
            log.error("提取图片失败: {}", documentName, e);
        }
        
        return imageMap;
    }
    
    /**
     * 将图片与表格行关联
     * @param document Word文档对象
     * @param imageMap 图片路径映射
     * @return 行图片映射 Map<"行号_类型", 图片路径>
     */
    public Map<String, String> associateImagesWithRows(XWPFDocument document, Map<String, String> imageMap) {
        Map<String, String> rowImageMap = new HashMap<>();
        
        try {
            List<XWPFTable> tables = document.getTables();
            
            // 将图片路径转换为有序列表
            List<String> imagePaths = new ArrayList<>(imageMap.values());
            int imageIndex = 0;
            
            for (XWPFTable table : tables) {
                List<XWPFTableRow> rows = table.getRows();
                
                // 跳过表头，从数据行开始
                for (int rowIndex = 1; rowIndex < rows.size(); rowIndex++) {
                    XWPFTableRow row = rows.get(rowIndex);
                    List<XWPFTableCell> cells = row.getTableCells();
                    
                    // 检查整改前照片列（通常是第5列，索引4）
                    if (cells.size() > 4) {
                        String hasImage = extractImageFromCell(cells.get(4), imageMap);
                        if ("HAS_IMAGE".equals(hasImage) && imageIndex < imagePaths.size()) {
                            String beforeImagePath = imagePaths.get(imageIndex++);
                            rowImageMap.put((rowIndex - 1) + "_before", beforeImagePath);
                            log.debug("行{}整改前照片: {}", rowIndex - 1, beforeImagePath);
                        }
                    }
                    
                    // 检查改造后照片列（通常是第7列，索引6）
                    if (cells.size() > 6) {
                        String hasImage = extractImageFromCell(cells.get(6), imageMap);
                        if ("HAS_IMAGE".equals(hasImage) && imageIndex < imagePaths.size()) {
                            String afterImagePath = imagePaths.get(imageIndex++);
                            rowImageMap.put((rowIndex - 1) + "_after", afterImagePath);
                            log.debug("行{}改造后照片: {}", rowIndex - 1, afterImagePath);
                        }
                    }
                }
                
                // 通常一个文档只有一个表格，找到后退出
                break;
            }
            
            log.info("图片关联完成，共处理{}张图片，分配到{}个位置", imagePaths.size(), rowImageMap.size());
            
        } catch (Exception e) {
            log.error("关联图片与行失败", e);
        }
        
        return rowImageMap;
    }
    
    /**
     * 从单元格中提取图片
     * 注意：由于POI API限制，无法精确获取单元格中的具体图片
     * 这里返回null，由上层逻辑按顺序分配图片
     */
    private String extractImageFromCell(XWPFTableCell cell, Map<String, String> imageMap) {
        try {
            List<XWPFParagraph> paragraphs = cell.getParagraphs();
            
            for (XWPFParagraph paragraph : paragraphs) {
                List<XWPFRun> runs = paragraph.getRuns();
                
                for (XWPFRun run : runs) {
                    List<XWPFPicture> pictures = run.getEmbeddedPictures();
                    
                    if (!pictures.isEmpty()) {
                        // 返回标记，表示这个单元格有图片
                        // 具体的图片路径由上层按顺序分配
                        return "HAS_IMAGE";
                    }
                }
            }
            
        } catch (Exception e) {
            log.debug("从单元格提取图片失败", e);
        }
        
        return null;
    }
    
    /**
     * 保存图片到文件
     */
    private boolean saveImageToFile(XWPFPictureData picture, String filePath) {
        try {
            File file = new File(filePath);
            File parentDir = file.getParentFile();
            
            if (!parentDir.exists()) {
                parentDir.mkdirs();
            }
            
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fos.write(picture.getData());
            }
            
            // 验证文件是否成功保存
            if (file.exists() && file.length() > 0) {
                log.debug("图片保存成功: {}, 大小: {} bytes", filePath, file.length());
                return true;
            } else {
                log.warn("图片保存失败或文件为空: {}", filePath);
                return false;
            }
            
        } catch (Exception e) {
            log.error("保存图片到文件失败: {}", filePath, e);
            return false;
        }
    }
    
    /**
     * 生成图片文件名
     */
    private String generateImageFileName(String originalFileName, int index) {
        String extension = getFileExtension(originalFileName);
        return String.format("image_%03d%s", index + 1, extension);
    }
    
    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return ".jpg"; // 默认扩展名
        }
        
        String extension = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        
        // 验证是否为有效的图片扩展名
        Set<String> validExtensions = Set.of(".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff");
        if (validExtensions.contains(extension)) {
            return extension;
        } else {
            log.warn("不支持的图片格式: {}, 使用默认格式 .jpg", extension);
            return ".jpg";
        }
    }
    
    /**
     * 清理文件名，移除非法字符
     */
    private String sanitizeFileName(String fileName) {
        if (fileName == null) {
            return "unknown";
        }
        
        // 移除或替换非法字符
        return fileName.replaceAll("[\\\\/:*?\"<>|]", "_")
                      .replaceAll("\\s+", "_")
                      .trim();
    }
    
    /**
     * 获取图片的MIME类型
     */
    public String getImageMimeType(String filePath) {
        String extension = getFileExtension(filePath).toLowerCase();
        
        switch (extension) {
            case ".jpg":
            case ".jpeg":
                return "image/jpeg";
            case ".png":
                return "image/png";
            case ".gif":
                return "image/gif";
            case ".bmp":
                return "image/bmp";
            case ".tiff":
                return "image/tiff";
            default:
                return "image/jpeg"; // 默认
        }
    }
    
    /**
     * 验证图片文件
     */
    public boolean validateImageFile(String filePath) {
        try {
            File file = new File(filePath);
            
            // 检查文件是否存在
            if (!file.exists()) {
                log.warn("图片文件不存在: {}", filePath);
                return false;
            }
            
            // 检查文件大小
            long fileSize = file.length();
            if (fileSize == 0) {
                log.warn("图片文件为空: {}", filePath);
                return false;
            }
            
            // 检查文件大小是否过大（例如超过10MB）
            if (fileSize > 10 * 1024 * 1024) {
                log.warn("图片文件过大: {} ({} bytes)", filePath, fileSize);
                return false;
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("验证图片文件失败: {}", filePath, e);
            return false;
        }
    }
    
    /**
     * 清理临时图片文件
     */
    public void cleanupTempImages(String documentName) {
        try {
            String baseDir = "uploads/word_images/" + 
                java.time.LocalDate.now().toString().replace("-", "/") + "/" +
                sanitizeFileName(documentName) + "/";
            
            File dir = new File(baseDir);
            if (dir.exists()) {
                File[] files = dir.listFiles();
                if (files != null) {
                    for (File file : files) {
                        if (file.delete()) {
                            log.debug("删除临时图片文件: {}", file.getAbsolutePath());
                        }
                    }
                }
                
                // 删除空目录
                if (dir.delete()) {
                    log.debug("删除临时目录: {}", baseDir);
                }
            }
            
        } catch (Exception e) {
            log.warn("清理临时图片文件失败: {}", documentName, e);
        }
    }
}